/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.devel.designpatterns.visitor;

import com.devel.designpatterns.composite.Composite;
import com.devel.designpatterns.composite.Leaf;
import java.io.IOException;
import java.io.PrintStream;
import org.codehaus.jackson.JsonEncoding;
import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonGenerator;

/**
 *
 * @author wm.devel
 */
public class JacksonJSONEncodeVisitor extends Visitor {

    private PrintStream out;
    private JsonFactory f;
    private JsonGenerator g;
    private int level = 0;
    private int countComposite = -1;
    private int countLeaf = 0;

    public JacksonJSONEncodeVisitor(PrintStream out) {
        this.out = out;
        f = new JsonFactory();
        try {
            g = f.createJsonGenerator(out, JsonEncoding.UTF8);
            g.useDefaultPrettyPrinter();
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    public JacksonJSONEncodeVisitor() {
        this(System.out);
    }

    @Override
    public void visitCompositeStart(Composite composite) {
        try {
            level++;
            g.writeStartObject();
                String objName = "Composite";
                if (++countComposite > 0)
                    objName = objName + "_" + countComposite;
                g.writeObjectFieldStart(objName);
                g.writeNumberField("size", composite.size());
                g.writeArrayFieldStart("children");
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    @Override
    public void visitCompositeEnd(Composite composite) {
        try {
                g.writeEndArray();
                g.writeEndObject();
            g.writeEndObject();
            level--;
            if (level == 0) {
                g.close();
            }
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }

    @Override
    public void visitLeaf(Leaf leaf) {
        try {
            g.writeStartObject();
            String objName = "Leaf";
            if (++countLeaf > 0)
                objName = objName + "_" + countLeaf;
            g.writeObjectFieldStart(objName);
                g.writeStringField("text", leaf.getText());
                g.writeEndObject();
            g.writeEndObject();
            g.flush();
        } catch (IOException ex) {
            throw new RuntimeException(ex);
        }
    }
}
